const { ccclass, property } = cc._decorator;

@ccclass
export default class Drag extends cc.Component {

    @property(cc.Boolean)
    xEnable: boolean = true;
    @property(cc.Boolean)
    yEnable: boolean = true;
    @property(cc.Vec2)
    maxPos: cc.Vec2 = cc.v2(2000, 2000);
    @property(cc.Vec2)
    minPos: cc.Vec2 = cc.v2(-2000, -2000);

    moveTarget: cc.Node = null;
    hasDraggedOnce = false;
    isDraging = false;
    isLocked = false;
    index: number = 0;

    private onDragStart: Function;
    private onDraging: Function;
    private onDragFinish: Function;
    private thisObj: any;

    private previousPos: cc.Vec2;

    setDragEvents(startDragCallabck: Function, dragingCallabck: Function, finishDragCallback: Function, thisObj?: any) {
        this.onDragStart = startDragCallabck;
        this.onDraging = dragingCallabck;
        this.onDragFinish = finishDragCallback;
        this.thisObj = thisObj;
    }

    start() {
        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchDown, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchUp, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchUp, this);
    }

    onTouchDown(e: cc.Event.EventTouch) {
        if (this.enabled && !this.isLocked) {
            this.enabled = true;
            this.previousPos = e.getLocation();
            this.isDraging = true;
            this.hasDraggedOnce = true;
            if (this.onDragStart) {
                this.onDragStart.call(this.thisObj, e, this.index);
            }
        }
    }

    onTouchMove(e: cc.Event.EventTouch) {
        let currTouchPos = e.getLocation();
        if (this.enabled && !this.isLocked && this.isDraging) {
            if (!this.moveTarget) {
                this.moveTarget = this.node;
            }
            if (this.xEnable) {
                let deltaX = currTouchPos.x - this.previousPos.x;
                let x = this.moveTarget.x;
                x += deltaX;
                if (x < this.minPos.x) {
                    x = this.minPos.x
                }
                if (x > this.maxPos.x) {
                    x = this.maxPos.x
                }
                this.moveTarget.x = x;
            }
            if (this.yEnable) {
                let deltaY = currTouchPos.y - this.previousPos.y;
                let y = this.moveTarget.y;
                y += deltaY;
                if (y < this.minPos.y) {
                    y = this.minPos.y
                }
                if (y > this.maxPos.y) {
                    y = this.maxPos.y
                }
                this.moveTarget.y = y;
            }
            if (this.onDraging) {
                this.onDraging.call(this.thisObj, e, this.index);
            }
        }
        this.previousPos = currTouchPos;
    }

    onTouchUp(e: cc.Event.EventTouch) {
        if (this.isDraging) {
            this.isDraging = false;
            if (this.onDragFinish) {
                this.onDragFinish.call(this.thisObj, e, this.index);
            }
        }
    }

    static addDrag(target: cc.Node, index = 0): Drag {
        if (!target) {
            console.error('target为null');
            return;
        }
        let drag = target.getComponent(Drag);
        if (!drag) {
            drag = target.addComponent(Drag);
        }
        drag.index = index;
        drag.enabled = true;
        return drag;
    }

    static setEnable(target: cc.Node, b: boolean) {
        if (!target) {
            console.error('target为null');
            return;
        }
        let drag = target.getComponent(Drag);
        if (drag) {
            drag.enabled = b;
        }
    }

    static setLock(target: cc.Node, b: boolean) {
        if (!target) {
            console.error('target为null');
            return;
        }
        let drag = target.getComponent(Drag);
        if (drag) {
            drag.isLocked = b;
        }
    }
}
